/**
 * @class   wosh::SecurityToken
 * @brief   Represent a security token, used by messages to store the creator
 *          information (object and user).
 *



 *
 ****************************************************************************
 * @version $Id: SecurityToken.h 2863 2010-08-07 04:28:58Z alex $
 * @author  Alessandro Polo
 ****************************************************************************/
/* Copyright (c) 2007-2010, WOSH - Wide Open Smart Home 
 * by Alessandro Polo - OpenSmartHome.com
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *     * Neither the name of the OpenSmartHome.com WOSH nor the
 *       names of its contributors may be used to endorse or promote products
 *       derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY Alessandro Polo ''AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL Alessandro Polo BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 ****************************************************************************/

#ifndef __WOSH_Core_SecurityToken_H__
 #define __WOSH_Core_SecurityToken_H__

 #include <woshDefs.h>
 #include <core/Serialization.h>
 #include <string>

namespace wosh {

 namespace persistence {
  namespace qt {
	class EncoderXml_Qt_SecurityToken;
  };
 };
 class Object;
 class Message;
 class SecurityManager;
 class SecurityTokenProvider;
 class SecurityTokenAuthenticator;

class SecurityToken : public ISerializable
 {
	WOSH_SERIALIZABLE_ABSTRACT(wosh::SecurityToken)
	WOSH_COMPARE_RTTI(wosh::SecurityToken)

	public:
		enum AUTHENTICATION_MODE {
			AUTH_UNKNOWN		= 0x0000,
			AUTH_EXTERNAL		= 0x0001,
			AUTH_PASSWORD		= 0x0002,
			AUTH_BIOMETRICS		= 0x0010
		 };

		enum SOURCE_ACCESS {
			ACCESS_UNKNOWN		= 0x0000,
			ACCESS_IMPLICIT		= 0x0001,
			ACCESS_LOCALHOST	= 0x0002,
			ACCESS_NETWORK		= 0x0004,
			ACCESS_EXTERNAL		= 0x0008,

			ACCESS_ANY			= 0x000F // used as mask
		 };

	public:
		/**
		 * @brief  Copy constructor.
		 * @param m [in] the source object to be copied
		 */
		SecurityToken( const SecurityToken& m ) {
			*this = m;
		 }
		/**
		 * @brief  Empty destructor.
		 */
		virtual ~SecurityToken() { }

		virtual double getVersion() const = 0;
		virtual SOURCE_ACCESS getSourceAccess() const = 0;


/** @name Getters
 * @{
 ******************************************************************************/
	public:
		inline int64 getID() const									{ return this->token_id; }
		inline int64 getTimeStamp() const							{ return this->token_ts; }
		inline unsigned long getTTL() const							{ return this->ttl; }

		inline const std::string& getUsername() const				{ return this->user_name; }

		inline const std::string& getCreatorUUID() const			{ return this->creator_uuid; }
		inline const std::string& getTargetUUID() const				{ return this->target_uuid; }
		inline const std::string& getProviderUUID() const			{ return this->provider_uuid; }
		inline const std::string& getCreatorHostName() const		{ return this->host_name; }

		inline const std::string& getAuthenticatorName() const		{ return this->authenticator_classname; }
		inline double getAuthenticatorVersion() const				{ return this->authenticator_ver; }

		inline AUTHENTICATION_MODE getAuthenticationMode() const	{ return this->authentication_mode; }

//@}
/** @name Operators Overloading
 * @{
 ******************************************************************************/
	public:
		virtual SecurityToken& operator=(const SecurityToken& m);
		virtual bool operator==(const SecurityToken &other) const;
 		virtual bool operator!=(const SecurityToken &other) const { return !(*this == other);  }

//@}
/** @name Serialization interface
 * @{
 ******************************************************************************/
	public:
		virtual std::string toString() const;
		virtual bool updateHash( DataHashContext* hash_context ) const;
//@}

	protected:
		SecurityToken();

		friend class wosh::SecurityManager;
		friend class wosh::SecurityTokenProvider;
		friend class wosh::SecurityTokenAuthenticator;

	protected:
		int64 token_id;				///< unique random ID
		int64 token_ts;				///< creation timestamp
		unsigned long ttl;			///< time-to-live in seconds, 0=no-timeout

		std::string user_name;
		std::string creator_uuid;

		std::string target_uuid;
		std::string target_hash;

		std::string provider_uuid;

		std::string host_name;		///< name of the host (such as wosh28)
		std::string authenticator_classname;
		double authenticator_ver;

		AUTHENTICATION_MODE authentication_mode;

	private:
		bool init_signed;

		friend class wosh::persistence::qt::EncoderXml_Qt_SecurityToken;

}; // class def


class SecurityTokenProvider : public virtual IReflection
 {
	WOSH_CLASSNAME(wosh::SecurityTokenProvider)
	WOSH_CLASS_ABSTRACT(true)
	WOSH_CLONE_ABSTRACT(wosh::SecurityTokenProvider)

	public:
		SecurityTokenProvider();
		SecurityTokenProvider( const SecurityTokenProvider& ) { }
		virtual ~SecurityTokenProvider() { }

	public:
		virtual double getVersion() const = 0;

		virtual SecurityToken* signMessage( Message* message, const Object* creator ) const;
		virtual SecurityToken* signMessage( Message* message, const std::string& username ) const;

		// deprecated
		virtual SecurityToken* createToken( const Object* creator, const std::string& username ) const;

	protected:
		virtual SecurityToken* createToken() const = 0;

		virtual void initToken(SecurityToken* st) const;
		virtual void updateToken( SecurityToken* st, const std::string& username ) const;
		virtual void updateToken( SecurityToken* st, const Object* creator ) const;
		virtual void setupTokenMessage( SecurityToken* st, Message* message, const Object* creator ) const;
		virtual void finalizeSigning( SecurityToken* st, Message* message ) const;

	public:
		virtual WRESULT setAuthenticationMode( SecurityToken::AUTHENTICATION_MODE mode, const std::string& mode_options );


	protected:
		std::string uuid;
		SecurityToken::AUTHENTICATION_MODE auth_mode;
		std::string auth_mode_options;

}; // class def


class SecurityTokenAuthenticator : public virtual IReflection
 {
	WOSH_CLASSNAME(wosh::SecurityTokenAuthenticator)
	WOSH_CLASS_ABSTRACT(true)
//	WOSH_CLONE_ABSTRACT(wosh::SecurityTokenAuthenticator)

	public:
		SecurityTokenAuthenticator() { }
		virtual ~SecurityTokenAuthenticator() { }

	public:
		virtual bool isSupported( const char* provider_classname, double version = 0.0 ) const = 0;

		virtual double getVersion() const = 0;

	public:
		virtual WRESULT validate( const Object* target, const SecurityToken* token ) const;
		virtual WRESULT validateMessage( const Message* message ) const;

	public:
		virtual WRESULT validateToken( const SecurityToken* token ) const = 0;

	private:
		SecurityTokenAuthenticator( const SecurityTokenAuthenticator& ) { }

}; // class def


//------------------------------------------------------------------------------------------

class SecurityTokenImplicit : public SecurityToken
 {
	WOSH_SERIALIZABLE(wosh::SecurityTokenImplicit)

	public:
		SecurityTokenImplicit()
			: SecurityToken() { }

		/**
		 * @brief  Copy constructor.
		 * @param m [in] the source object to be copied
		 */
		SecurityTokenImplicit( const SecurityTokenImplicit& m )
			: SecurityToken(m) { }

	public:
		inline double getVersion() const				{ return 1.0; }
		inline SOURCE_ACCESS getSourceAccess() const	{ return SecurityToken::ACCESS_IMPLICIT; }

}; // class def


class SecurityTokenProviderImplicit : public SecurityTokenProvider
{
	WOSH_CLASSNAME(wosh::SecurityTokenProviderImplicit)
	WOSH_CLASS_ABSTRACT(false)
	WOSH_CLONE_CONSTRUCTOR(wosh::SecurityTokenProviderImplicit)

	public:
		SecurityTokenProviderImplicit()
			: SecurityTokenProvider() { }
		SecurityTokenProviderImplicit( const SecurityTokenProviderImplicit& m )
			: SecurityTokenProvider(m) { }
		~SecurityTokenProviderImplicit() { }

	public:
		double getVersion() const	{ return 0.0; }

	protected:
		SecurityToken* createToken() const;


}; // class def

//------------------------------------------------------------------------------------------

class SecurityTokenProxy : public SecurityToken
 {
	WOSH_SERIALIZABLE(wosh::SecurityTokenProxy)

	public:
		SecurityTokenProxy()
			: SecurityToken(), source_token(NULL) { }

		/**
		 * @brief  Copy constructor.
		 * @param m [in] the source object to be copied
		 */
		SecurityTokenProxy( const SecurityTokenProxy& m )
			: SecurityToken(m), source_token(NULL) { }

	public:
		void setSource( SecurityToken* source_token );

	public:
		inline double getVersion() const					{ return 1.0; }
		inline SOURCE_ACCESS getSourceAccess() const		{ return SecurityToken::ACCESS_UNKNOWN; }

		inline bool hasSourceToken() const					{ return (this->source_token != NULL); }
		inline const SecurityToken* getSourceToken() const	{ return this->source_token; }

	protected:
		SecurityToken* source_token;

}; // class def


class SecurityTokenProviderProxy : public SecurityTokenProvider
{
	WOSH_CLASSNAME(wosh::SecurityTokenProviderProxy)
	WOSH_CLASS_ABSTRACT(false)
	WOSH_CLONE_CONSTRUCTOR(wosh::SecurityTokenProviderProxy)

	public:
		SecurityTokenProviderProxy()
			: SecurityTokenProvider() { }
		SecurityTokenProviderProxy( const SecurityTokenProviderProxy& m )
			: SecurityTokenProvider(m) { }
		~SecurityTokenProviderProxy() { }

	public:
		double getVersion() const	{ return 0.0; }

	public:
		SecurityToken* signMessage( Message* message, const SecurityToken* source_token, const Object* creator ) const;
		SecurityToken* signMessage( Message* message, const SecurityToken* source_token, const std::string& username ) const;

	protected:
		SecurityToken* createToken() const;


}; // class def




}; // namespace wosh

#endif //__WOSH_Core_SecurityToken_H__
